#ifndef INTERRUPT_H
#define INTERRUPT_H

#include <stdint.h>

// 中断处理函数类型（无参数无返回值，适配RISC-V中断上下文）
typedef void (*interrupt_handler_t)(void);

// 中断优先级（0为最低，7为最高，与PLIC硬件优先级寄存器兼容）
typedef enum {
    IRQ_PRIORITY_0 = 0,  // 最低优先级（默认）
    IRQ_PRIORITY_1,
    IRQ_PRIORITY_2,
    IRQ_PRIORITY_3,
    IRQ_PRIORITY_4,
    IRQ_PRIORITY_5,
    IRQ_PRIORITY_6,
    IRQ_PRIORITY_7       // 最高优先级
} irq_priority_t;

// 中断源定义（需与硬件中断号对应，PLIC/CLINT设备映射）
typedef enum {
    IRQ_NONE = 0,        // 无效中断（保留）
    IRQ_TIMER = 1,       // 时钟中断（CLINT，机器模式定时器）
    IRQ_SOFTWARE = 2,    // 软件中断（CLINT，多核心间通信）
    IRQ_UART = 3,        // UART串口中断（PLIC，如UART0）
    IRQ_GPIO = 5,        // GPIO中断（PLIC，通用输入输出）
    // 可扩展其他设备中断（如磁盘、网络等，需与硬件手册匹配）
} irq_num_t;

// 中断向量表项结构（支持共享中断，每个IRQ可注册多个处理函数）
#define MAX_HANDLERS_PER_IRQ 4  // 单个中断最大共享处理函数数量
typedef struct {
    interrupt_handler_t handlers[MAX_HANDLERS_PER_IRQ];  // 处理函数列表
    irq_priority_t priority;                             // 中断优先级（硬件生效）
    uint8_t handler_count;                               // 已注册函数数量
    uint8_t enabled;                                     // 使能标记（1=使能，0=禁用）
} irq_descriptor_t;

// 全局中断向量表（大小需覆盖所有可能的IRQ号）
#define MAX_IRQ_NUM 32  // 支持的最大中断数量（可根据硬件扩展）
extern irq_descriptor_t irq_vector_table[MAX_IRQ_NUM];

// RISC-V中断原因（cause）解析宏（补充硬件相关定义）
#define CAUSE_INTERRUPT_MASK (1ULL << 63)  // cause最高位：1=中断，0=异常
#define CAUSE_IS_INTERRUPT(cause) ((cause) & CAUSE_INTERRUPT_MASK)  // 判断是否为中断
#define CAUSE_IRQ_NUM(cause) ((cause) & ~CAUSE_INTERRUPT_MASK)       // 提取中断号（清除最高位）

// 机器模式（M-mode）中断原因具体值（与RISC-V规范一致）
#define CAUSE_M_TIMER     7   // 机器模式时钟中断（CLINT）
#define CAUSE_M_SOFTWARE  3   // 机器模式软件中断（CLINT）
#define CAUSE_M_EXTERNAL  11  // 机器模式外部中断（PLIC）

// 中断控制接口
void trap_init(void);  // 初始化中断系统（CLINT/PLIC配置、向量表清空）

// 注册中断处理函数（返回0成功，-1失败：参数无效/函数数量满）
int register_interrupt(irq_num_t irq, interrupt_handler_t h, irq_priority_t prio);

// 注销中断处理函数（返回0成功，-1失败：未找到函数/参数无效）
int unregister_interrupt(irq_num_t irq, interrupt_handler_t h);

void enable_interrupt(irq_num_t irq);   // 开启指定中断（更新硬件使能位）
void disable_interrupt(irq_num_t irq);  // 关闭指定中断（清除硬件使能位）

// 中断处理核心函数（由汇编入口调用，解析cause并分发到注册的处理函数）
void trap_handler(uint64_t cause, uint64_t epc);

#endif
